﻿
#include"D3D12Interface.h"

#include <d3d12.h>
#include <dxgi1_6.h>
#include <atlbase.h>

#include<GLFW/glfw3.h>
#define GLFW_EXPOSE_NATIVE_WIN32 1 //暴露出win32相关的原生接口
#include<GLFW/glfw3native.h>

#include"stb_image.h"

#include<vector>

#include<d3dx12.h>
#include<d3dcompiler.h>

#include"HRESULTStrings.h"
#include"APICallErrorInfo.h"

#include"DDSTextureLoader/DDSTextureLoader12.h"

//定义 ThrowIfFailed：
#define ThrowIfFailed(FunctionCallResult)\
{\
	if (FAILED(FunctionCallResult))\
	{\
		throw APICallErrorInfo(#FunctionCallResult, GetHRESULTMessage(FunctionCallResult),__FILE__,__LINE__);\
	}\
}


//将string转换成wstring
static std::wstring string2wstring(std::string str)
{
    std::wstring result;
    //获取缓冲区大小，并申请空间，缓冲区大小按字符计算  
    int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);
    TCHAR* buffer = new TCHAR[len + 1];
    //多字节编码转换成宽字节编码  
    MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), buffer, len);
    buffer[len] = '\0';             //添加字符串结尾  
    //删除缓冲区并返回值  
    result.append(buffer);
    delete[] buffer;
    return result;
}

//D3D12的顶点缓存
class D3D12_VertexBuffer : public AbstractVertexBuffer
{
public:
    //顶点缓冲数据
    ComPtr<ID3D12Resource> VertexBuffer;
    //D3D12的顶点缓冲View
    D3D12_VERTEX_BUFFER_VIEW VertexBufferView;
    //索引缓冲数据
    ComPtr<ID3D12Resource> IndexBuffer;
    //D3D12的索引缓冲View
    D3D12_INDEX_BUFFER_VIEW IndexBufferView;
};

//D3D12的图形管线数据
class D3D12_GraphicsPipeline : public CommonPipelineStateObject
{
public:
    D3D12_GraphicsPipeline(GraphicsPipelineInfo Info) :CommonPipelineStateObject(Info) {}

    //根参数对应哪个资源
    std::vector<unsigned int> RootParameterResourceIndex;

    //根签名
    ComPtr<ID3D12RootSignature> RootSignature;
    //D3D12的图形管线对象
    ComPtr<ID3D12PipelineState> PipelineState;
    //视窗
    CD3DX12_VIEWPORT Viewport;
    //裁剪矩形
    CD3DX12_RECT ScissorRect;
};

//D3D12着色器资源的通用接口
class D3D12ResourceCommon : CommonShaderResource
{
public:
    D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle;
    D3D12_GPU_DESCRIPTOR_HANDLE GPUDescriptorHandle;
};

//D3D12的UniformBuffer
class D3D12_UniformBuffer : public D3D12ResourceCommon
{
public:
    void* BufferAddress;	//Buffer的CPU地址
    uint32_t BufferSize;	//Buffer的尺寸
    ComPtr<ID3D12Resource> Buffer;
    UINT8* CbvDataBegin;
};

//D3D12的纹理数据
class D3D12_TextureData : public D3D12ResourceCommon
{
public:
    ComPtr<ID3D12Resource> TextureResource;
};

//对原先描述符堆的一层封装
class D3D12DescriptorHeapWrapper
{
    ComPtr<ID3D12DescriptorHeap> Heap;
    
    //一个Descriptor所占的尺寸
    UINT8 IncrementSize;

    //已经分配的Descriptor个数
    unsigned int AllocateCount;

    //总个数 
    unsigned int DescriptorAmount;
public:
    D3D12DescriptorHeapWrapper(D3D12_DESCRIPTOR_HEAP_TYPE Type, ComPtr<ID3D12Device> Device)
    {
        AllocateCount = 0;
        
        DescriptorAmount = 128;//给一个应该较大的值

        //创建Heap
        {
            D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
            rtvHeapDesc.NumDescriptors = DescriptorAmount;
            rtvHeapDesc.Type = Type;
            if (Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
                rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
            else
                rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
            ThrowIfFailed(Device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&Heap)));
        }    
        
        //获得Descriptor的尺寸
        IncrementSize = Device->GetDescriptorHandleIncrementSize(Type);
    }

    ID3D12DescriptorHeap* GetRawPointer() { return Heap.Get(); }

    //分配一个Descriptor，返回序号
    unsigned int AllocateOneDescriptor()
    {
        if (AllocateCount < DescriptorAmount)
        {
            AllocateCount++;
            return (AllocateCount - 1);
        }
        else
            return -1;
    }

    //得到一个Descriptor序号对应的CPUHandle
    D3D12_CPU_DESCRIPTOR_HANDLE GetCPUHandle(int DescriptorIndex)
    {
        CD3DX12_CPU_DESCRIPTOR_HANDLE handle(Heap->GetCPUDescriptorHandleForHeapStart());

        return handle.Offset(DescriptorIndex, IncrementSize);
    }
    //得到一个Descriptor序号对应的GPUHandle
    D3D12_GPU_DESCRIPTOR_HANDLE GetGPUHandle(int DescriptorIndex)
    {
        CD3DX12_GPU_DESCRIPTOR_HANDLE handle(Heap->GetGPUDescriptorHandleForHeapStart());

        return handle.Offset(DescriptorIndex, IncrementSize);
    }
};

bool D3D12Interface::Init(GLFWwindow* window)
{
    p_window = window;

    UINT dxgiFactoryFlags = 0; //创建DXGIFactory时的flag

#if defined(_DEBUG)
    // Enable the debug layer (requires the Graphics Tools "optional feature").
    // NOTE: Enabling the debug layer after device creation will invalidate the active device.
    {
        ComPtr<ID3D12Debug> debugController;
        if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
        {
            debugController->EnableDebugLayer();

            // Enable additional debug layers.
            dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
        }
    }
#endif

    HRESULT hr = S_OK;

    //获得窗口尺寸
    int WindowWidth, WindowHeight;
    glfwGetWindowSize(window, &WindowWidth, &WindowHeight);


    //----------------------------------------------------------------------------------------------------
    //1.使用D3D12CreateDevice函数创建出 Device
    //----------------------------------------------------------------------------------------------------
    ThrowIfFailed(D3D12CreateDevice(
        nullptr                     //pAdapter: If NULL, D3D12CreateDevice will choose the primary adapter.
        , D3D_FEATURE_LEVEL_11_0    //MinimumFeatureLevel: The minimum feature level required for successful device creation.
        , IID_PPV_ARGS(&Device)));   //ppDevice: Pointer to returned interface.


    //----------------------------------------------------------------------------------------------------
    //2.创建CommandQueue
    //----------------------------------------------------------------------------------------------------
    D3D12_COMMAND_QUEUE_DESC queueDesc = {};
    queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
    queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
    ThrowIfFailed(Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&CommandQueue)));


    //----------------------------------------------------------------------------------------------------
    //3.创建SwapChain
    //----------------------------------------------------------------------------------------------------
    //描述交换链  
    DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
    swapChainDesc.BufferCount = SwapChainBufferCount;
    swapChainDesc.Width = WindowWidth;
    swapChainDesc.Height = WindowHeight;
    swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
    swapChainDesc.SampleDesc.Count = 1;

    //创建DXGIFactory
    ComPtr<IDXGIFactory4> factory;
    CreateDXGIFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory));

    //创建交换链
    ComPtr<IDXGISwapChain1> swapChain;
    ThrowIfFailed(factory->CreateSwapChainForHwnd(
        CommandQueue.Get(),        // Swap chain needs the queue so that it can force a flush on it.
        glfwGetWin32Window(window),
        &swapChainDesc,
        nullptr,
        nullptr,
        &swapChain));

    //将IDXGISwapChain1转换为IDXGISwapChain3
    ThrowIfFailed(swapChain.As(&SwapChain));

    //记录当前后缓冲索引号
    CurrentBackBufferIndex = SwapChain->GetCurrentBackBufferIndex();


    //----------------------------------------------------------------------------------------------------
    //4.创建RenderTarget
    //----------------------------------------------------------------------------------------------------
    //创建RTV的Descriptor堆
    {
        RTVHeap = new D3D12DescriptorHeapWrapper(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, Device);
    }
    //创建RenderTarget
    {
        // 为每一个BackBuffer创建RTV
        for (UINT n = 0; n < SwapChainBufferCount; n++)
        {
            //分配Descriptor
            int DescriptorIndex = RTVHeap->AllocateOneDescriptor();
            
            SwapChain->GetBuffer(n, IID_PPV_ARGS(&RenderTargets[n]));
            Device->CreateRenderTargetView(RenderTargets[n].Get(), nullptr, RTVHeap->GetCPUHandle(DescriptorIndex));
        }
    }
    //创建CBV和SRV的Descriptor堆
    {
        // Describe and create a constant buffer view (CBV) descriptor heap.
        // Flags indicate that this descriptor heap can be bound to the pipeline 
        // and that descriptors contained in it can be referenced by a root table.
        CBVSRVHeap = new D3D12DescriptorHeapWrapper(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, Device);
    }
    //创建DSV的Descriptor堆
    {
        // Describe and create a depth stencil view (DSV) descriptor heap.
        // Each frame has its own depth stencils (to write shadows onto) 
        // and then there is one for the scene itself.
        DSVHeap = new D3D12DescriptorHeapWrapper(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, Device);
    }


    //----------------------------------------------------------------------------------------------------
    //5.创建CommandAllocator和CommandList
    //----------------------------------------------------------------------------------------------------
    //创建 CommandAllocator
    ThrowIfFailed(Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&CommandAllocator)));

    //创建 command list.
    ThrowIfFailed(Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, CommandAllocator.Get(), nullptr, IID_PPV_ARGS(&CommandList)));

    // Command lists are created in the recording state, but there is nothing
    // to record yet. The main loop expects it to be closed, so close it now.
    CommandList->Close();


    //----------------------------------------------------------------------------------------------------
    //6.创建同步用的东西
    //----------------------------------------------------------------------------------------------------
    //创建Fence
    Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence));

    //创建一个event对象
    m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);


    //----------------------------------------------------------------------------------------------------
    //7.创建 Depth Stencil View
    //----------------------------------------------------------------------------------------------------
    {
        CD3DX12_RESOURCE_DESC DepthTextureDesc(
            D3D12_RESOURCE_DIMENSION_TEXTURE2D,
            0,
            static_cast<UINT>(WindowWidth),
            static_cast<UINT>(WindowHeight),
            1,
            1,
            DXGI_FORMAT_D32_FLOAT,
            1,
            0,
            D3D12_TEXTURE_LAYOUT_UNKNOWN,
            D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL | D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE);

        D3D12_CLEAR_VALUE clearValue;    // Performance tip: Tell the runtime at resource creation the desired clear value.
        clearValue.Format = DXGI_FORMAT_D32_FLOAT;
        clearValue.DepthStencil.Depth = 1.0f;
        clearValue.DepthStencil.Stencil = 0;

        ThrowIfFailed(Device->CreateCommittedResource(
            &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
            D3D12_HEAP_FLAG_NONE,
            &DepthTextureDesc,
            D3D12_RESOURCE_STATE_DEPTH_WRITE,
            &clearValue,
            IID_PPV_ARGS(&DepthStencil)));

        // Create the depth stencil view.
        Device->CreateDepthStencilView(DepthStencil.Get(), nullptr, DSVHeap->GetCPUHandle(0));
    }

    return true;
}

void D3D12Interface::BeginRecordCommandList()
{
    // Command list allocators can only be reset when the associated
    // command lists have finished execution on the GPU; apps should use 
    // fences to determine GPU execution progress.
    ThrowIfFailed(CommandAllocator->Reset());

    // However, when ExecuteCommandList() is called on a particular command 
    // list, that command list can then be reset at any time and must be before 
    // re-recording.
    ThrowIfFailed(CommandList->Reset(CommandAllocator.Get(), nullptr));

    // Indicate that the back buffer will be used as a render target.
    CommandList->ResourceBarrier(1
        , &CD3DX12_RESOURCE_BARRIER::Transition(RenderTargets[CurrentBackBufferIndex].Get()
            , D3D12_RESOURCE_STATE_PRESENT
            , D3D12_RESOURCE_STATE_RENDER_TARGET));
}

void D3D12Interface::EndRecordCommandList()
{
    // Indicate that the back buffer will now be used to present.
    CommandList->ResourceBarrier(1, 
        &CD3DX12_RESOURCE_BARRIER::Transition(RenderTargets[CurrentBackBufferIndex].Get()
            , D3D12_RESOURCE_STATE_RENDER_TARGET
            , D3D12_RESOURCE_STATE_PRESENT));

    CommandList->Close();
}

void D3D12Interface::ExecuteCommandLists()
{
    ID3D12CommandList* ppCommandLists[] = { CommandList.Get() };
    CommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
}

void D3D12Interface::Present()
{
    // Present the frame
    SwapChain->Present(1, 0);

    WaitForPreviousFrame();

    //获得当前的后缓冲的序号
    CurrentBackBufferIndex = SwapChain->GetCurrentBackBufferIndex();
}
void D3D12Interface::WaitForPreviousFrame()
{
    // WAITING FOR THE FRAME TO COMPLETE BEFORE CONTINUING IS NOT BEST PRACTICE.
    // This is code implemented as such for simplicity. The D3D12HelloFrameBuffering
    // sample illustrates how to use fences for efficient resource usage and to
    // maximize GPU utilization.

    //新的围栏值应该比旧的更新
    const UINT64 NewFenceValue = m_fence->GetCompletedValue() + 1;

    //设定当队列完成后，围栏将变为新的围栏值
    CommandQueue->Signal(m_fence.Get(), NewFenceValue);

    if (m_fence->GetCompletedValue() < NewFenceValue)
    {
        //设定围栏对象达到新的值时触发m_fenceEvent事件
        m_fence->SetEventOnCompletion(NewFenceValue, m_fenceEvent);
        //等待直到m_fenceEvent事件触发
        WaitForSingleObject(m_fenceEvent, INFINITE);
    }
}



void D3D12Interface::BeginRenderPass(float ClearColor[4])
{
    auto rtvHandle = RTVHeap->GetCPUHandle(CurrentBackBufferIndex);
    auto dsvHandle = DSVHeap->GetCPUHandle(0);
    
    CommandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);

    // Record commands.
    const float clearColor[] = { ClearColor[0],  ClearColor[1],  ClearColor[2],  ClearColor[3] };
    CommandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);

    //Clear深度缓冲
    CommandList->ClearDepthStencilView(dsvHandle, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
}

void D3D12Interface::EnumerateGraphicsCards()
{
    //创建IDXGIFactory
    CComPtr<IDXGIFactory2> mdxgiFactory;
    CreateDXGIFactory2(0, IID_PPV_ARGS(&mdxgiFactory));

    std::cout << "IDXGIFactory2::EnumAdapters : " << std::endl;

    //遍历所有的Adapter
    int	i = 0;
    IDXGIAdapter* adapter = nullptr;
    while (mdxgiFactory->EnumAdapters(i, &adapter) != DXGI_ERROR_NOT_FOUND)
    {
        DXGI_ADAPTER_DESC desc;				
        adapter->GetDesc(&desc);
        
        //打印出Description
        std::wcout << desc.Description << std::endl;	

        ++i;
    }
}


AbstractVertexBuffer* D3D12Interface::CreateVertexBuffer(const std::vector<float>& VertexAttributeData,unsigned int StrideInBytes, const std::vector<unsigned int>& IndexData)
{
    D3D12_VertexBuffer* result = new D3D12_VertexBuffer();

    //顶点缓冲总尺寸
    const UINT vertexBufferSize = VertexAttributeData.size() * sizeof(float);

    // Note: using upload heaps to transfer static data like vert buffers is not 
    // recommended. Every time the GPU needs it, the upload heap will be marshalled 
    // over. Please read up on Default Heap usage. An upload heap is used here for 
    // code simplicity and because there are very few verts to actually transfer.
    ThrowIfFailed(Device->CreateCommittedResource(
        &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
        D3D12_HEAP_FLAG_NONE,
        &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize),
        D3D12_RESOURCE_STATE_GENERIC_READ,
        nullptr,
        IID_PPV_ARGS(&result->VertexBuffer)));

    // Copy the triangle data to the vertex buffer.
    UINT8* pVertexDataBegin;
    CD3DX12_RANGE readRange(0, 0);        // We do not intend to read from this resource on the CPU.
    ThrowIfFailed(result->VertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin)));
    memcpy(pVertexDataBegin, VertexAttributeData.data(), vertexBufferSize);
    result->VertexBuffer->Unmap(0, nullptr);

    // Initialize the vertex buffer view.
    result->VertexBufferView.BufferLocation = result->VertexBuffer->GetGPUVirtualAddress();
    result->VertexBufferView.StrideInBytes = StrideInBytes;
    result->VertexBufferView.SizeInBytes = vertexBufferSize;

    //索引数据
    {
        //索引数据缓冲总尺寸
        const UINT indexBufferSize = IndexData.size() * sizeof(unsigned int);

        ThrowIfFailed(Device->CreateCommittedResource(
            &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
            D3D12_HEAP_FLAG_NONE,
            &CD3DX12_RESOURCE_DESC::Buffer(indexBufferSize),
            D3D12_RESOURCE_STATE_GENERIC_READ,
            nullptr,
            IID_PPV_ARGS(&result->IndexBuffer)));

        // Copy the triangle data to the vertex buffer.
        UINT8* pVertexDataBegin;
        CD3DX12_RANGE readRange(0, 0);        // We do not intend to read from this resource on the CPU.
        ThrowIfFailed(result->IndexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin)));
        memcpy(pVertexDataBegin, IndexData.data(), indexBufferSize);
        result->IndexBuffer->Unmap(0, nullptr);

        // Initialize the vertex buffer view.
        result->IndexBufferView.BufferLocation = result->IndexBuffer->GetGPUVirtualAddress();
        result->IndexBufferView.Format = DXGI_FORMAT_R32_UINT;
        result->IndexBufferView.SizeInBytes = indexBufferSize;
    }

    return result;
}
void D3D12Interface::SetVertexBuffer(AbstractVertexBuffer* Buffer)
{
    D3D12_VertexBuffer* vb = (D3D12_VertexBuffer*)Buffer;

    //输入装配阶段（Input-Assembler Stage）设置索引缓冲
    CommandList->IASetIndexBuffer(&vb->IndexBufferView);
    //输入装配阶段（Input-Assembler Stage）设置顶点缓冲
    CommandList->IASetVertexBuffers(0, 1, &vb->VertexBufferView);
}

HRESULT D3D12Interface::CompileShader(std::string ShaderFile, LPCSTR pEntrypoint, LPCSTR pTarget, UINT Flags1, UINT Flags2, ID3DBlob** ppCode)
{
    ID3DBlob* errorBlob = nullptr;//容纳返回的错误
    HRESULT result = D3DCompileFromFile(string2wstring(ShaderFile).c_str(), nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE, pEntrypoint, pTarget, Flags1, Flags2, ppCode, &errorBlob);
    if (FAILED(result))
    {
        //如果失败，则显示错误
        if (errorBlob)
        {
            MessageBoxA(nullptr, (char*)errorBlob->GetBufferPointer(), "编译Shader失败", MB_OK);
            errorBlob->Release();
        }

        if (*ppCode)
            (*ppCode)->Release();
    }
    return result;
}

CommonPipelineStateObject* D3D12Interface::CreateGraphicsPipeline(GraphicsPipelineInfo Info)
{
    D3D12_GraphicsPipeline* result = new D3D12_GraphicsPipeline(Info);

    // Create a root signature consisting of a descriptor table with a single CBV.
    {
        D3D12_FEATURE_DATA_ROOT_SIGNATURE featureData = {};

        // This is the highest version the sample supports. If CheckFeatureSupport succeeds, the HighestVersion returned will not be greater than this.
        featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1;

        if (FAILED(Device->CheckFeatureSupport(D3D12_FEATURE_ROOT_SIGNATURE, &featureData, sizeof(featureData))))
        {
            featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_0;
        }

        //根据资源的布局得到根参数和sampler
        std::vector<CD3DX12_ROOT_PARAMETER1> RootParameters;
        std::vector< D3D12_STATIC_SAMPLER_DESC> Samplers;
        std::vector< CD3DX12_DESCRIPTOR_RANGE1> ranges(Info.ShaderResourceSlots.size());
        {
            //for (auto& ResourceSlot : Info.ShaderResourceSlots)
            for (int ResourceIndex = 0; ResourceIndex < Info.ShaderResourceSlots.size(); ResourceIndex++)
            {
                const ShaderResourceSlotInfo& ResourceSlot = Info.ShaderResourceSlots[ResourceIndex];

                if (ResourceSlot.Type == ShaderResourceType::Sampler)
                {
                    //纹理sampler，当前暂时是硬编码的数据
                    D3D12_STATIC_SAMPLER_DESC sampler = {};
                    sampler.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
                    sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
                    sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
                    sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
                    sampler.MipLODBias = 0;
                    sampler.MaxAnisotropy = 0;
                    sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
                    sampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
                    sampler.MinLOD = 0.0f;
                    sampler.MaxLOD = D3D12_FLOAT32_MAX;
                    sampler.ShaderRegister = 5;     //着色器中寄存器的编号，现在表示(s5)
                    sampler.RegisterSpace = 0;
                    sampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;

                    Samplers.push_back(sampler);
                }
                else
                {
                    D3D12_DESCRIPTOR_RANGE_TYPE Type;
                    if (ResourceSlot.Type == ShaderResourceType::UniformBuffer)
                        Type = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;//ConstantBuffer
                    else if (ResourceSlot.Type == ShaderResourceType::Texture)
                        Type = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;//ShaderResourceView

                    D3D12_SHADER_VISIBILITY Visibility;
                    if (ResourceSlot.Type == ShaderResourceType::UniformBuffer)
                        Visibility = D3D12_SHADER_VISIBILITY_ALL;//全部可见
                    else if (ResourceSlot.Type == ShaderResourceType::Texture)
                        Visibility = D3D12_SHADER_VISIBILITY_PIXEL;//仅像素着色器可见

                    ranges[ResourceIndex].Init(
                        Type                                //描述符类型
                        , 1                                 //个数
                        , ResourceSlot.BindingIndex         //着色器中寄存器的编号
                        , 0                                 //寄存器空间
                        , D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC);

                    CD3DX12_ROOT_PARAMETER1 rootParameter;
                    RootParameters.push_back(rootParameter);
                    RootParameters[RootParameters.size() - 1].InitAsDescriptorTable(
                        1
                        , &ranges[ResourceIndex]
                        , Visibility);     //可见性，现在表示全部shader可见

                    result->RootParameterResourceIndex.push_back(ResourceIndex);
                }
            }
        }


        //设定根签名的flag，来跳过不需要的shader阶段
        D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags =
            D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |      //接受输入装配阶段
            D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |            //拒绝Hull着色器
            D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |          //拒绝Domain着色器
            D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS;         //拒绝几何着色器

        //创建根签名的描述结构体
        CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc;
        rootSignatureDesc.Init_1_1(
            RootParameters.size()       //RootParameter个数
            , RootParameters.data()     //RootParameter数组
            , Samplers.size()                         //StaticSampler个数
            , Samplers.data()                  //StaticSampler数组
            , rootSignatureFlags);

        //序列化根签名
        ComPtr<ID3DBlob> Serialized_Signature;
        ComPtr<ID3DBlob> Error;
        ThrowIfFailed(D3DX12SerializeVersionedRootSignature(&rootSignatureDesc, featureData.HighestVersion, &Serialized_Signature, &Error));
        
        //创建根签名
        ThrowIfFailed(Device->CreateRootSignature(0, Serialized_Signature->GetBufferPointer(), Serialized_Signature->GetBufferSize(), IID_PPV_ARGS(&result->RootSignature)));
    }

    //PipelineState
    {
        //顶点着色器路径
        std::string VSFilePath = "shaders/hlsl/" + Info.VertexShaderFile + ".hlsl";
        //像素着色器路径
        std::string PSFilePath = "shaders/hlsl/" + Info.PixelShaderFile + ".hlsl";

        ComPtr<ID3DBlob> vertexShader;
        ComPtr<ID3DBlob> pixelShader;

#if defined(_DEBUG)
        // Enable better shader debugging with the graphics debugging tools.
        UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#else
        UINT compileFlags = 0;
#endif

        ThrowIfFailed(CompileShader(VSFilePath, "Main", "vs_5_0", compileFlags, 0, &vertexShader));
        ThrowIfFailed(CompileShader(PSFilePath, "Main", "ps_5_0", compileFlags, 0, &pixelShader));

  
        //顶点布局：
        std::vector<D3D12_INPUT_ELEMENT_DESC> inputElementDescs;
        {
            std::vector<VertexInputAttributeDescription>& VertexInputAttributes = result->VertexInputAttributes;

            //偏移：
            UINT AlignedByteOffset = 0;

            for (int i = 0; i < VertexInputAttributes.size(); i++)
            {
                D3D12_INPUT_ELEMENT_DESC desc;

                //HLSL中的语义
                switch (VertexInputAttributes[i].Type)
                {
                case VIA_POSITION:
                    desc.SemanticName = "POSITION";
                    break;
                case VIA_NORMAL:
                    desc.SemanticName = "NORMAL";
                    break;
                case VIA_TANGENT:
                    desc.SemanticName = "TANGENT";
                    break;
                case VIA_COLOR:
                    desc.SemanticName = "COLOR";
                    break;
                case VIA_TEXCOORD:
                    desc.SemanticName = "TEXCOORD";
                    break;
                default:
                    break;
                }
                //HLSL中的语义序号
                desc.SemanticIndex = 0;
                
                //格式：
                switch (VertexInputAttributes[i].Float32Cout)
                {
                case 2:
                    desc.Format = DXGI_FORMAT_R32G32_FLOAT;
                    break;
                case 3:
                    desc.Format = DXGI_FORMAT_R32G32B32_FLOAT;
                    break;
                case 4:
                    desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
                    break;
                default:
                    break;
                }

                desc.InputSlot = 0;

                //偏移
                desc.AlignedByteOffset = AlignedByteOffset;
                AlignedByteOffset += VertexInputAttributes[i].Float32Cout * sizeof(float);

                desc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;

                desc.InstanceDataStepRate = 0;

                //最后加入列表
                inputElementDescs.push_back(desc);
            }
        }

        //光栅化状态
        D3D12_RASTERIZER_DESC RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
        RasterizerState.CullMode = D3D12_CULL_MODE_NONE;//不剔除

        // Describe and create the graphics pipeline state object (PSO).
        D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
        psoDesc.InputLayout = { inputElementDescs.data(), (UINT)inputElementDescs.size() };
        psoDesc.pRootSignature = result->RootSignature.Get();
        psoDesc.VS = CD3DX12_SHADER_BYTECODE(vertexShader.Get());
        psoDesc.PS = CD3DX12_SHADER_BYTECODE(pixelShader.Get());
        psoDesc.RasterizerState = RasterizerState;
        psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
        psoDesc.DepthStencilState.DepthEnable = true;
        psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
        psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
        psoDesc.DepthStencilState.StencilEnable = FALSE;
        psoDesc.SampleMask = UINT_MAX;
        psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
        psoDesc.NumRenderTargets = 1;
        psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
        psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT;
        psoDesc.SampleDesc.Count = 1;
        ThrowIfFailed(Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&result->PipelineState)));
    }

    //7.设置视窗 和 裁剪矩形
    {
        //获得窗口尺寸
        int WindowWidth, WindowHeight;
        glfwGetWindowSize(p_window, &WindowWidth, &WindowHeight);

        result->Viewport.Width = (FLOAT)WindowWidth;
        result->Viewport.Height = (FLOAT)WindowHeight;
        result->Viewport.MinDepth = 0.0f;
        result->Viewport.MaxDepth = 1.0f;
        result->Viewport.TopLeftX = 0;
        result->Viewport.TopLeftY = 0;

        result->ScissorRect.left = 0;
        result->ScissorRect.top = 0;
        result->ScissorRect.right = (LONG)(WindowWidth);
        result->ScissorRect.bottom = (LONG)(WindowHeight);
       
    }


    return result;
}
void D3D12Interface::SetGraphicsPipeline(CommonPipelineStateObject* Pipeline)
{
    D3D12_GraphicsPipeline* dx12Pipeline = (D3D12_GraphicsPipeline*)Pipeline;

    CommandList->SetPipelineState(dx12Pipeline->PipelineState.Get());

    CommandList->SetGraphicsRootSignature(dx12Pipeline->RootSignature.Get());

    CommandList->RSSetViewports(1, &dx12Pipeline->Viewport);
    CommandList->RSSetScissorRects(1, &dx12Pipeline->ScissorRect);

    CommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
}

AbstractUniformBuffer* D3D12Interface::CreateUniformBuffer(UniformBufferCreateInfo CreateInfo)
{
    D3D12_UniformBuffer* result = new D3D12_UniformBuffer();
    
    const UINT constantBufferSize = (CreateInfo.BufferSize + 255) & 0xff00;    // 必须是256的整数倍

    result->BufferSize = constantBufferSize;
    result->BufferAddress = CreateInfo.BufferAddress;    

    ThrowIfFailed(Device->CreateCommittedResource(
        &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
        D3D12_HEAP_FLAG_NONE,
        &CD3DX12_RESOURCE_DESC::Buffer(constantBufferSize),
        D3D12_RESOURCE_STATE_GENERIC_READ,
        nullptr,
        IID_PPV_ARGS(&result->Buffer)));

    // Describe and create a constant buffer view.
    D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
    cbvDesc.BufferLocation = result->Buffer->GetGPUVirtualAddress();
    cbvDesc.SizeInBytes = constantBufferSize;

    //分配一个Descriptor
    int DescriptorIndex = CBVSRVHeap->AllocateOneDescriptor();

    result->CPUDescriptorHandle = CBVSRVHeap->GetCPUHandle(DescriptorIndex);
    result->GPUDescriptorHandle = CBVSRVHeap->GetGPUHandle(DescriptorIndex);

    //创建View
    Device->CreateConstantBufferView(&cbvDesc, result->CPUDescriptorHandle);
    
    // Map and initialize the constant buffer. We don't unmap this until the
    // app closes. Keeping things mapped for the lifetime of the resource is okay.
    CD3DX12_RANGE readRange(0, 0);        // We do not intend to read from this resource on the CPU.
    ThrowIfFailed(result->Buffer->Map(0, &readRange, reinterpret_cast<void**>(&result->CbvDataBegin)));
    memcpy(result->CbvDataBegin, result->BufferAddress, result->BufferSize);
    
    return (AbstractUniformBuffer*)(result);
}
void D3D12Interface::UpdateUniformBuffer(AbstractUniformBuffer* UniformBuffer)
{
    D3D12_UniformBuffer* dx_ub = (D3D12_UniformBuffer*)UniformBuffer;

    memcpy(dx_ub->CbvDataBegin, dx_ub->BufferAddress, dx_ub->BufferSize);
}

AbstractTextureData* D3D12Interface::CreateTexture(std::string ImageFile)
{
    D3D12_TextureData* result = new D3D12_TextureData();

    //开始录制CommandList命令
    ThrowIfFailed(CommandList->Reset(CommandAllocator.Get(), nullptr));
   
    //读取图片
    int texWidth, texHeight, texChannels;
    stbi_uc* pixels = stbi_load(ImageFile.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
    const UINT TexturePixelSize = 4;//由于是 rgb_alpha 所以是4通道

    //纹理描述
    D3D12_RESOURCE_DESC textureDesc = {};
    textureDesc.MipLevels = 1;
    textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    textureDesc.Width = texWidth;
    textureDesc.Height = texHeight;
    textureDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
    textureDesc.DepthOrArraySize = 1;
    textureDesc.SampleDesc.Count = 1;
    textureDesc.SampleDesc.Quality = 0;
    textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;

    //创建TextureResource：实际用的纹理资源    
    ThrowIfFailed(Device->CreateCommittedResource(
        &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
        D3D12_HEAP_FLAG_NONE,
        &textureDesc,
        D3D12_RESOURCE_STATE_COPY_DEST,
        nullptr,
        IID_PPV_ARGS(&result->TextureResource)));
 
    //创建中间资源
    ComPtr<ID3D12Resource> textureUploadHeap;
    {
        //尺寸：
        const UINT64 uploadBufferSize = GetRequiredIntermediateSize(result->TextureResource.Get(), 0, 1);

        // Create the GPU upload buffer.
        ThrowIfFailed(Device->CreateCommittedResource(
            &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
            D3D12_HEAP_FLAG_NONE,
            &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),
            D3D12_RESOURCE_STATE_GENERIC_READ,
            nullptr,
            IID_PPV_ARGS(&textureUploadHeap)));
    }

    //将数据复制给中间资源，然后从中间资源复制给实际的资源
    {
        D3D12_SUBRESOURCE_DATA textureData = {};
        textureData.pData = pixels;
        textureData.RowPitch = texWidth * TexturePixelSize;
        textureData.SlicePitch = textureData.RowPitch * texHeight;
        UpdateSubresources(CommandList.Get(), result->TextureResource.Get(), textureUploadHeap.Get(), 0, 0, 1, &textureData);
    }
       
    //使用资源屏障进行资源转换：
    CommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(result->TextureResource.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));

    // Describe and create a SRV for the texture.
    {
        D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
        srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
        srvDesc.Format = textureDesc.Format;
        srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
        srvDesc.Texture2D.MipLevels = 1;

        //分配一个Descriptor
        int DescriptorIndex = CBVSRVHeap->AllocateOneDescriptor();

        result->CPUDescriptorHandle = CBVSRVHeap->GetCPUHandle(DescriptorIndex);
        result->GPUDescriptorHandle = CBVSRVHeap->GetGPUHandle(DescriptorIndex);

        Device->CreateShaderResourceView(result->TextureResource.Get(), &srvDesc, result->CPUDescriptorHandle);
    }
    
    //结束命令录制
    ThrowIfFailed(CommandList->Close());
   
    //执行命令
    ID3D12CommandList* ppCommandLists[] = { CommandList.Get() };
    CommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
    //在此等待命令执行完
    WaitForPreviousFrame();

    return (AbstractTextureData*)result;
};

AbstractTextureData* D3D12Interface::CreateCubeMapTexture(std::vector<std::string> FaceImageFiles)
{
    D3D12_TextureData* result = new D3D12_TextureData();

    //开始录制CommandList命令
    ThrowIfFailed(CommandList->Reset(CommandAllocator.Get(), nullptr));

    //读取图片
    int texWidth, texHeight, texChannels;
    std::vector<stbi_uc*> pixels;
    for (unsigned int i = 0; i < FaceImageFiles.size(); i++)
        pixels.push_back(stbi_load(FaceImageFiles[i].c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha));
    const UINT TexturePixelSize = 4;//由于是 rgb_alpha 所以是4通道

    //纹理描述
    D3D12_RESOURCE_DESC textureDesc = {};
    textureDesc.MipLevels = 1;
    textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    textureDesc.Width = texWidth;
    textureDesc.Height = texHeight;
    textureDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
    textureDesc.DepthOrArraySize = 6;   //CubeMap需要6张贴图
    textureDesc.SampleDesc.Count = 1;
    textureDesc.SampleDesc.Quality = 0;
    textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;

    //创建TextureResource：实际用的纹理资源    
    ThrowIfFailed(Device->CreateCommittedResource(
        &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
        D3D12_HEAP_FLAG_NONE,
        &textureDesc,
        D3D12_RESOURCE_STATE_COPY_DEST,
        nullptr,
        IID_PPV_ARGS(&result->TextureResource)));

    //创建中间资源
    ComPtr<ID3D12Resource> textureUploadHeap;
    {
        //尺寸：
        const UINT64 uploadBufferSize = GetRequiredIntermediateSize(result->TextureResource.Get(), 0, 6);

        // Create the GPU upload buffer.
        ThrowIfFailed(Device->CreateCommittedResource(
            &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
            D3D12_HEAP_FLAG_NONE,
            &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),
            D3D12_RESOURCE_STATE_GENERIC_READ,
            nullptr,
            IID_PPV_ARGS(&textureUploadHeap)));
    }

    //将数据复制给中间资源，然后从中间资源复制给实际的资源
    {
        std::vector<D3D12_SUBRESOURCE_DATA> textureDatas;

        for (int i = 0; i < 6; i++)
        {
            D3D12_SUBRESOURCE_DATA textureData = {};
            textureData.pData = pixels[i];
            textureData.RowPitch = texWidth * TexturePixelSize;
            textureData.SlicePitch = textureData.RowPitch * texHeight;
            
            textureDatas.push_back(textureData);
        }

        UpdateSubresources(CommandList.Get(), result->TextureResource.Get(), textureUploadHeap.Get(), 0, 0
            , static_cast<UINT>(textureDatas.size())
            , textureDatas.data());
    }

    //使用资源屏障进行资源转换：
    CommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(result->TextureResource.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));

    // Describe and create a SRV for the texture.
    {
        D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
        srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
        srvDesc.Format = textureDesc.Format;
        srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
        srvDesc.Texture2D.MipLevels = 1;

        //分配一个Descriptor
        int DescriptorIndex = CBVSRVHeap->AllocateOneDescriptor();

        result->CPUDescriptorHandle = CBVSRVHeap->GetCPUHandle(DescriptorIndex);
        result->GPUDescriptorHandle = CBVSRVHeap->GetGPUHandle(DescriptorIndex);

        Device->CreateShaderResourceView(result->TextureResource.Get(), &srvDesc, result->CPUDescriptorHandle);
    }

    //结束命令录制
    ThrowIfFailed(CommandList->Close());

    //执行命令
    ID3D12CommandList* ppCommandLists[] = { CommandList.Get() };
    CommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
    //在此等待命令执行完
    WaitForPreviousFrame();

    return (AbstractTextureData*)result;
}

AbstractTextureData* D3D12Interface::CreateCubeMapTextureFromDDS(std::string DDSFile)
{
    D3D12_TextureData* result = new D3D12_TextureData();
    
    //开始录制CommandList命令
    ThrowIfFailed(CommandList->Reset(CommandAllocator.Get(), nullptr));
  
    std::unique_ptr<uint8_t[]> ddsData;//读取到的DDS数据
    std::vector<D3D12_SUBRESOURCE_DATA> textureDatas;//读取到的纹理数据

    DirectX::DDS_ALPHA_MODE alphaMode = DirectX::DDS_ALPHA_MODE::DDS_ALPHA_MODE_UNKNOWN;

    //读取DDS数据，创建result->TextureResource：实际用的纹理资源   
    DirectX::LoadDDSTextureFromFile(
        Device.Get()                        //In_ ID3D12Device* d3dDevice,
        , string2wstring(DDSFile).c_str()   //_In_z_ const wchar_t* szFileName,
        , &result->TextureResource          //_Outptr_ ID3D12Resource** texture,
        , ddsData                           //std::unique_ptr<uint8_t[]>& ddsData,
        , textureDatas                      //std::vector<D3D12_SUBRESOURCE_DATA>& subresources,
        , SIZE_MAX                          //size_t maxsize = 0,
        , &alphaMode                        //_Out_opt_ DDS_ALPHA_MODE* alphaMode = nullptr,
        , nullptr);                         //_Out_opt_ bool* isCubeMap = nullptr
    

    //创建中间资源
    ComPtr<ID3D12Resource> textureUploadHeap;
    {
        //尺寸：
        UINT64 uploadBufferSize = GetRequiredIntermediateSize(result->TextureResource.Get(), 0, static_cast<UINT>(textureDatas.size()));

        // Create the GPU upload buffer.
        ThrowIfFailed(Device->CreateCommittedResource(
            &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
            D3D12_HEAP_FLAG_NONE,
            &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),
            D3D12_RESOURCE_STATE_GENERIC_READ,
            nullptr,
            IID_PPV_ARGS(&textureUploadHeap)));
    }

    //将数据复制给中间资源，然后从中间资源复制给实际的资源
    {
        UpdateSubresources(CommandList.Get(), result->TextureResource.Get(), textureUploadHeap.Get(), 0, 0
            , static_cast<UINT>(textureDatas.size())
            , textureDatas.data());
    }


    //使用资源屏障进行资源转换：
    CommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(result->TextureResource.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));

    // Describe and create a SRV for the texture.
    {
        D3D12_RESOURCE_DESC textureDesc = result->TextureResource->GetDesc();
        
        D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; 
        srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; 
        srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; 
        srvDesc.TextureCube.MostDetailedMip = 0; 
        srvDesc.TextureCube.MipLevels = textureDesc.MipLevels;
        srvDesc.TextureCube.ResourceMinLODClamp = 0.0f; 
        srvDesc.Format = textureDesc.Format;
       
         //分配一个Descriptor
        int DescriptorIndex = CBVSRVHeap->AllocateOneDescriptor();

        result->CPUDescriptorHandle = CBVSRVHeap->GetCPUHandle(DescriptorIndex);
        result->GPUDescriptorHandle = CBVSRVHeap->GetGPUHandle(DescriptorIndex);

        Device->CreateShaderResourceView(result->TextureResource.Get(), &srvDesc, result->CPUDescriptorHandle);
    }

    //结束命令录制
    ThrowIfFailed(CommandList->Close());

    //执行命令
    ID3D12CommandList* ppCommandLists[] = { CommandList.Get() };
    CommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
    //在此等待命令执行完
    WaitForPreviousFrame();

    return (AbstractTextureData*)result;
}

void D3D12Interface::CmdDrawInstanced(
    unsigned int VertexCountPerInstance,
    unsigned int InstanceCount,
    unsigned int StartVertexLocation,
    unsigned int StartInstanceLocation)
{
    CommandList->DrawInstanced(VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation);
}
void D3D12Interface::CmdDrawIndexedInstanced(
    unsigned int IndexCountPerInstance,
    unsigned int InstanceCount,
    unsigned int StartIndexLocation,
    int BaseVertexLocation,
    unsigned int StartInstanceLocation)
{
    CommandList->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation);
}

void D3D12Interface::CmdBindPipelineCurrentDescriptorSets(CommonPipelineStateObject* PSO)
{
    D3D12_GraphicsPipeline* Pipeline = (D3D12_GraphicsPipeline*)PSO;
    
    //设置Descriptor堆
    ID3D12DescriptorHeap* ppHeap_cbvsrv[] = { CBVSRVHeap->GetRawPointer() };
    CommandList->SetDescriptorHeaps(_countof(ppHeap_cbvsrv), ppHeap_cbvsrv);
    //设置DescriptorTabe
    for (int RootParameterIndex = 0; RootParameterIndex < Pipeline->RootParameterResourceIndex.size(); RootParameterIndex++)
    {
        //哪一个资源
        unsigned int ResourceIndex = Pipeline->RootParameterResourceIndex[RootParameterIndex];

        //资源
        D3D12ResourceCommon* res = (D3D12ResourceCommon*)(PSO->CurrentShaderResources[ResourceIndex]);

        //设定
        CommandList->SetGraphicsRootDescriptorTable(RootParameterIndex, res->GPUDescriptorHandle);
    }
}